
package ClientGraphics;

import GameEngine.GameConstants.Graphic;
import GameEngine.GameConstants.Levels;
import GameEngine.GameConstants.Thing;
import GameEngine.Level;
import GameEngine.Vector;
import Objects.BasicObject;
import Objects.GameObject;
import Objects.SpawnPoint;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

/**
 * This class will be used to test graphics functionality, through an abstraction, no actual game
 * or server.
 * @author mhfowler
 */
public class GraphicsTest {

    /* millisecond between gamestate updates */
    final int MBGU = 100;

    JFrame mainFrame;
    GraphicsMain gMain;

    public GraphicsTest() {
        Dimension levelDimension = new Dimension(1000,1000);
        gMain = new GraphicsMain(Levels.ABSTRACT, levelDimension,1000,1000);
        mainFrame = new JFrame("test");
        mainFrame.setVisible(true);
        mainFrame.setSize(new Dimension(levelDimension.width,levelDimension.height));
        mainFrame.setResizable(true);
        mainFrame.add(gMain.getGraphicsPanel());
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel check = gMain.getGraphicsPanel();
        Graphics g = check.getGraphics();
        Graphics2D g2 = (Graphics2D) g;
        System.out.println("check");
        gMain.initialize();
        System.out.println("done construction");
    }


    public static void main(String[] args) {
       GraphicsTest thisTest = new GraphicsTest();
       thisTest.test(2, 1);
       /*
       for (int j=0; j<3; j++) {
           System.out.println("round " + j);
           int perspective = 2 -j;
            thisTest.test(2, perspective);
       }
        * */
 
}



    /* The second test showcases two characters moving about 500 pixels, over the course of 200 gamestate
     * updates.
     */
    public void test(int a, int perspective) {

        switch (a) {
            case 1:
        /* basic test of displaying two guys on simple background, transparent pixels,
         * overlap, flicker */
        List<BasicObject> test1 = createTestLevel(1);
        System.out.println("size " + test1.size());
        gMain.update(test1);
                break;
            case 2:
                /* this is a case for testing many update states with a timer */
                List<List<BasicObject>> gStates = new LinkedList<List<BasicObject>>();
                /* lets fill this list of game states */
                int counter = 1;
                List<BasicObject> temp;
                Vector move1 = new Vector(3,4);
                Vector move2 = new Vector(8,8);
                Vector move3 = new Vector(6,0);
                temp = createTestLevel(1);
                //gMain.setUID(temp.get(perspective).getId());
                while (counter <200) {
                    temp = createTestLevel(1);
                    // move everybody
                    temp.get(0).move(move1.scaleNew(counter));
                    temp.get(1).move(move2.scaleNew(counter));
                    // third guy exists only for 100 steps
                    if (counter<50) {
                        temp.get(2).move(move3.scaleNew(counter));
                    }
                    else if (counter == 50) {
                         temp.get(2).move(move3.scaleNew(counter));
                         temp.get(2).setExists(false);
                    }
                    else if (counter > 50) {
                        temp.remove(2);
                    }
                    // add gamestate to list
                    gStates.add(temp);
                    counter++;
                }
                /* now create timer which calls update every time interval, and pops off the next
                 * game state in the list */
                 Timer time = new Timer(MBGU,null);
                 TestListener tester = new TestListener(gMain, gStates, time);
                 time.addActionListener(tester);
                 time.start();
                break;
            case 3:
                    GameObject obj1 = GameEngine.LevelInitializer.objectConstructor(Thing.PLAYER, new Vector(1,0), new Vector (300,300), new Vector(50,50));
                    GameObject obj2 = GameEngine.LevelInitializer.objectConstructor(Thing.WALL, new Vector(1,0), new Vector (300,400), new Vector(500,10));
                    SpawnPoint obj3 = (SpawnPoint) GameEngine.LevelInitializer.objectConstructor(Thing.SPAWNPOINT, new Vector(0,1), new Vector (100,100), new Vector(50,50));
                    GameObject obj7 = GameEngine.LevelInitializer.objectConstructor(Thing.PLAYER, new Vector(1,0), new Vector (600,300), new Vector(50,50));
                    GameObject obj8 = GameEngine.LevelInitializer.objectConstructor(Thing.WALL, new Vector(1,0), new Vector (300,800), new Vector(800,10));
                    LinkedList<GameObject> list = new LinkedList<GameObject>();
                    obj1.setId((short)1);
                    obj2.setId((short)2);
                    obj3.setId((short)3);
                    obj7.setId((short)4);
                    obj8.setId((short)5);
                    list.add(obj1);
                    list.add(obj2);
                    list.add(obj3);
                    list.add(obj7);
                    list.add(obj8);
                    Level lev = new Level(list, 1000, 1500, 1, obj3);
                    List<BasicObject> toRender1 = lev.getBasics();
                    System.out.println("size :" + toRender1.size());
                    gMain.update(toRender1);
                    break;
            default:
                break;
        }
    }



    private class TestListener implements ActionListener {

        GraphicsMain gTest;
        Iterator<List<BasicObject>> gameStates;
        Timer parent;

        public TestListener(GraphicsMain g,List<List<BasicObject>> l, Timer p) {
            gTest = g;
            gameStates = l.iterator();
            parent = p;
        }



        public void actionPerformed(ActionEvent e) {
            if (gameStates.hasNext()) {
                gTest.update(gameStates.next());
            }
            else {
                System.out.println("finito");
                parent.stop();
            }
        }
    }







    // creates a list of basic object for testing, using a switch case for different tests
    public static List<BasicObject> createTestLevel(int a) {
        int counter = 0;
        List<BasicObject> toReturn = new LinkedList();
        switch (a) {
            case 1:
                short id = 1;
                BasicObject obj1 = createBasic(1,id, new Vector(1,0), new Vector(300,300), new Vector(60,60));
                toReturn.add(obj1);
                id++; 
                BasicObject obj2 = createBasic(1,id,  new Vector(1/Math.sqrt(2),1/Math.sqrt(2)), new Vector(100,100), new Vector(60,60));
                toReturn.add(obj2);
                id++; 
                BasicObject obj3 = createBasic(1,id,  new Vector(-1,0), new Vector(500,100), new Vector(160,160));
                toReturn.add(obj3);
                id++;
                BasicObject obj4 = createBasic(3,id,  new Vector(1,0), new Vector(500,500), new Vector(100,100));
                toReturn.add(obj4);
                break;
            default:
                break;
        }
        return toReturn;
    }


    // creates a basic object, for the purpose of testing
    // uses switch case with integer
    // also takes in id
    public static BasicObject createBasic(int a, short id, Vector dir, Vector center, Vector size) {
        BasicObject toReturn = null;
        switch (a) {
            case 1:
                toReturn = new BasicObject(dir, center, size, Graphic.PINKPLAYER_WALK);
                break;
            case 2:
                toReturn = new BasicObject(dir, center, size, Graphic.PINKPLAYER_WALK);
                break;
            case 3:
                toReturn = new BasicObject(dir, center, size, Graphic.PORTAL);
            default:
                break;
        }
        toReturn.setId(id);
        return toReturn;
    }



}
